package com.rtline.business.service.impl;

import java.math.BigDecimal;
import java.sql.Connection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import javax.sql.DataSource;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rtline.business.bloomfilter.BloomFilterService;
import com.rtline.business.cache.RedisCacheService;
import com.rtline.business.common.Result;
import com.rtline.business.mapper.UserMapper;
import com.rtline.business.model.UserEntity;
import com.rtline.business.service.UserOperationStrategy;
import com.rtline.business.service.UserService;
import com.rtline.business.vo.UserVo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * <p>UserServiceImpl .
 *
 * <p>change history:
 *
 * <pre>
 * date         defect       person          comments
 * --------------------------------------------------------------------------------
 * 2025/5/17    ********     Tao Ren    create file.
 * </pre>
 *
 * @author Tao Ren
 * @date 2025/5/17 21:12
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserOperationStrategyFactory strategyFactory;

    @Autowired
    private UserOperationStrategy2Factory strategyFactory2;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private BloomFilterService bloomFilterService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RedisCacheService redisCacheService;

    @Override
    public UserEntity getUserById(Long id) {
        // Step 1: 使用 Bloom Filter 检查用户 ID 是否可能在数据库中
        if (!bloomFilterService.contains(id)) {
            // 如果 Bloom Filter 显示它不存在，则直接返回 null
            return null;
        }

        // Step 2: 首先检查 Redis 缓存
        UserEntity user = null;
        Object cachedObject = redisCacheService.getUserFromCache(id);
        if (cachedObject instanceof LinkedHashMap) {
            // 将 LinkedHashMap 转换为 UserEntity
            user = objectMapper.convertValue(cachedObject, UserEntity.class);
        }
        if (user != null) {
            // 如果在缓存中找到，则返回缓存的用户
            return user;
        }

        // Step 3: 如果不在缓存中，则查询数据库
        user = userMapper.getUserById(id);

        // Step 4: 如果在数据库中找到 user，则添加到 Redis 缓存
        if (user != null) {
            redisCacheService.putUserToCache(user);
        }

        return user;
    }

    @Override
    public void insertUser(UserEntity user) {
        userMapper.insertUser(user);
    }

    @Override
    public List<UserEntity> findLimit(int i, int pageSize) {
        return userMapper.findLimit(i, pageSize);
    }

    @Override
    public Page<UserEntity> pageList(Page<UserEntity> page, Map<String, Object> params) {
        QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>();
        if (params != null) {
            // 动态构建查询条件
            params.forEach((key, value) -> {
                if (value != null) {
                    queryWrapper.like(key, value);
                }
            });
        }
        return this.page(page, queryWrapper);
    }

    @Override
    public Result operate(Map<String, Object> params) {

        String operationType = params.get("operationType").toString();
        UserVo user = getUserById(params.get("userId").toString()); // 假设有一个方法获取用户
        UserOperationStrategy strategy = strategyFactory2.getStrategy(operationType);
        if (strategy == null) {
            return new Result(500, "Unknown operation type: " + operationType);
        }
        strategy.execute(user, params);
        return new Result("Operation completed successfully");
    }

    private UserVo getUserById(String userId) {
        // 假设有一个方法从数据库获取用户
        return new UserVo();
    }

    @Override
    public CompletableFuture<String> getUserData(String userId) {

        // 创建一个CompletableFuture列表，用于存储每个任务
        CompletableFuture<String> nameFuture = getName(userId);
        CompletableFuture<String> emailFuture = getEmail(userId);
        CompletableFuture<String> addressFuture = getAddress(userId);

        // 使用CompletableFuture.allOf等待所有任务完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(nameFuture, emailFuture, addressFuture);

        // 当所有任务完成时，收集结果
        return allFutures.thenApply(v -> {
            String name = nameFuture.join();
            String email = emailFuture.join();
            String address = addressFuture.join();
            return "User Data: Name=" + name + ", Email=" + email + ", Address=" + address;
        });
    }

    public CompletableFuture<String> getName(String userId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Name" + userId;
        });
    }

    public CompletableFuture<String> getEmail(String userId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return userId + "@example.com";
        });
    }

    public CompletableFuture<String> getAddress(String userId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Address" + userId;
        });
    }

    @Override
    // @DistributedLock(key = "'update_balance_' + #userId")
    public void updateBalance(int userId) {
        UserEntity userEntity = userMapper.selectById(userId);
        //调用一次，累计加一
        userEntity.setBalance(userEntity.getBalance().add(BigDecimal.ONE));
        userMapper.updateById(userEntity);
    }

    @Transactional
    @Override
    public void testTransactional() {
        // 主线程操作
        // 主线程事务回滚，子线程事务没有回滚
        jdbcTemplate.execute("INSERT INTO users (email, name, password) VALUES ('1', '1', '1')");
        try {
            CompletableFuture.runAsync(() -> {
                // 子线程操作
                jdbcTemplate.execute("INSERT INTO `user` (`name`, `phone`, `create_by`, `remark`, `balance`) VALUES ('String1', 'String1', 'String1', 'cc', 1000.00);\n");
                throw new RuntimeException("子线程异常");
            }).get();
        } catch (Exception e) {
            throw new RuntimeException("子线程异常导致事务回滚", e);
        }
    }

    /**
     * 使用 TransactionTemplate 手动管理事务
     *
     * @author Tao Ren
     * @date 2025/6/28 17:19
     * @since 1.0.0
     */
    @Transactional
    @Override
    public void testTransactional2() {
        // 主线程操作
        jdbcTemplate.execute("INSERT INTO users (email, name, password) VALUES ('1', '1', '1')");

        // 获取主线程的数据库连接
        Connection conn = DataSourceUtils.getConnection(dataSource);
        try {
            CompletableFuture.runAsync(() -> {
                // 将主线程的连接绑定到子线程
                TransactionSynchronizationManager.bindResource(dataSource, new ConnectionHolder(conn));
                try {
                    // 子线程操作
                    jdbcTemplate.execute("INSERT INTO `user` (`name`, `phone`, `create_by`, `remark`, `balance`) VALUES ('String1', 'String1', 'String1', 'cc', 1000.00)");
                    throw new RuntimeException("子线程异常");
                } finally {
                    // 在子线程中释放连接
                    TransactionSynchronizationManager.unbindResource(dataSource);
                }
            }).get(); // 等待子线程完成
        } catch (Exception e) {
            throw new RuntimeException("子线程异常导致事务回滚", e);
        } finally {
            // 在主线程中释放连接
            DataSourceUtils.releaseConnection(conn, dataSource);
        }
    }
}
